package design.pattern.Lu18MementoPattern;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program JavaBase
 * @description: 备忘录模式 - 版本状态记录 回滚、撤销
 * @author: zhanglu
 * @create: 2022-05-19 14:24:00
 */
@Slf4j
public class MementoPattern06 {

    //配置文件
    @Data
    @AllArgsConstructor
    static class ConfigFile{
        //内容
        private String content;
    }

    //备忘录
    @Data
    static class ConfigMemento<T>{
        public static Integer index = 0;
        //版本号
        private String version;
        //更新时间
        private Date updateTime;
        //操作人
        private String operator;
        //配置文件
        private T t;
        public ConfigMemento(T t){
            this.setUpdateTime(new Date());
            this.t = t;
            this.version = versionBuild();
        }
        public String versionBuild(){
            try {
                index++;
                DecimalFormat df = new DecimalFormat();
                df.setMinimumIntegerDigits(6);
                df.setGroupingUsed(false);
                String format = df.format(index);
                Number n1 = df.parse(format.substring(0, 2));
                Number n2 = df.parse(format.substring(2, 4));
                Number n3 = df.parse(format.substring(4));
                return StrUtil.format("{}.{}.{}", n1.intValue(), n2.intValue(), n3.intValue());
            }catch (Exception e){}
            return "";
        }
    }

    //记录者
    static class ConfigOriginator<T>{
        private String operator;
        private ThreadLocal<T> threadLocal = new ThreadLocal<>();
        public ConfigOriginator(String operator){
            this.operator = operator;
        }
        public ConfigMemento save(){
            ConfigMemento configMemento = new ConfigMemento(threadLocal.get());
            configMemento.setOperator(operator);
            return configMemento;
        }
        public ConfigOriginator<T> setT(T t){
            threadLocal.set(t);
            return this;
        }
        public T getT(){
            return threadLocal.get();
        }
        public T clearT(){
            T t = threadLocal.get();
            threadLocal.remove();
            return t;
        }
    }

    static class SystemController{
        private Integer index = -1;
        private List<ConfigMemento> mementoList = new ArrayList<>();
        private Map<String, ConfigMemento> mementoMap = new ConcurrentHashMap<>();
        public void append(ConfigMemento memento){
            mementoList.add(memento);
            mementoMap.put(memento.getVersion(), memento);
            index++;
        }
        //回滚
        public ConfigMemento undo(){
            if(--index <= 0){
                return mementoList.get(0);
            }
            return mementoList.get(index);
        }
        //撤销
        public ConfigMemento redo(){
            if(++index > mementoList.size()){
                return mementoList.get(mementoList.size() - 1);
            }
            return mementoList.get(index);
        }
        //回滚到指定版本
        public ConfigMemento recover(String version){
            ConfigMemento memento = get(version);
            append(memento);
            return memento;
        }
        //回滚到指定版本
        public ConfigMemento recover(Integer index){
            ConfigMemento memento = mementoList.get(index);
            append(memento);
            return memento;
        }
        //查看指定版本的配置
        public ConfigMemento get(String version){
            return mementoMap.get(version);
        }
        public Integer getIndex(){
            return this.index;
        }
        //更新指针至任意位置
        public Integer updateIndex(Integer index){
            if(index > (mementoList.size())){
                this.updateIndex();
            }
            this.index = index;
            return this.index;
        }
        //更新指针至最新
        public Integer updateIndex(){
            this.index = mementoList.size() - 1;
            return this.index;
        }
    }

    @Test
    public void test01() throws ParseException {
        SystemController controller = new SystemController();
        ConfigOriginator originator = new ConfigOriginator("lu.zhang");

        controller.append(originator.setT(new ConfigFile("test01")).save());
        controller.append(originator.setT(new ConfigFile("test02")).save());
        controller.append(originator.setT(new ConfigFile("test03")).save());
        controller.append(originator.setT(new ConfigFile("test04")).save());

        ConfigMemento undo01 = controller.undo();
        log.info("历史配置-回滚undo--版本:{}-内容:{}", undo01.getVersion(),
                ((ConfigFile) originator.setT(undo01.getT()).getT()).getContent());
        ConfigMemento undo02 = controller.undo();
        log.info("历史配置-回滚undo--版本:{}-内容:{}", undo02.getVersion(),
                ((ConfigFile) originator.setT(undo02.getT()).getT()).getContent());
        ConfigMemento undo03 = controller.redo();
        log.info("历史配置-撤销redo--版本:{}-内容:{}", undo03.getVersion(),
                ((ConfigFile) originator.setT(undo03.getT()).getT()).getContent());
        ConfigMemento undo04 = controller.recover(undo01.getVersion());
        log.info("历史配置-回滚到任意版本:{}-版本:{}-内容:{}", undo01.getVersion(), undo04.getVersion(),
                ((ConfigFile) originator.setT(undo04.getT()).getT()).getContent());
        log.info(controller.getIndex().toString());
        log.info(controller.updateIndex().toString());
        originator.clearT();
    }

}
